package com.tt.payee.filter.webFliters;

import com.tt.payee.business.BusinessException;
import com.tt.payee.business.BusinessStatus;
import com.tt.payee.domain.TbPermission;
import com.tt.payee.domain.TbUser;
import com.tt.payee.service.login.TbUserService;
import com.tt.payee.utils.JwtTokenUtil;
import org.apache.tomcat.util.buf.MessageBytes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ：Tang
 * @date ：Created in 2020/8/19 14:43
 * @description：
 * @modified By：
 * @version: $
 */
@Component
public class PermissionFilter implements HandlerInterceptor {

    @Autowired
    TbUserService userService;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("access_token");
        int platform = Integer.parseInt(request.getHeader("platform"));

        //获取路由地址
        Object a = findCoyoteRequest(request);
        Field coyoteRequest = a.getClass().getDeclaredField("coyoteRequest");
        coyoteRequest.setAccessible(true);
        Object b = coyoteRequest.get(a);

        Field uriMB = b.getClass().getDeclaredField("uriMB");
        uriMB.setAccessible(true);
        MessageBytes c = (MessageBytes)uriMB.get(b);

        String path = c.getString();

        //判断是不是不用登录就可以过的接口
        for (String pUrl : new InterceptorConfig().getPassUrl()) {
            if (path.equals(pUrl)) {
                return true;
            }
        }

        //跳过支付回调接口
        if (path.contains("/km-terminal-api/userOrderController/notify") || path.contains("/km-terminal-api/userOrderController/aliNotify")) {
            return true;
        }

        if (platform != 1) {
            return true;
        }

        //1：后台tb用户；2：小程序app等sys用户
        int userType = JwtTokenUtil.getUserTypeFromToken(token);

        if (userType == 1) {
            return checkPermissionForBack(request, response, token);
        } else if (userType == 2) {
            return checkPermissionForFront(request, response);
        } else {
            return  checkPermissionForBack(request, response, token);
        }
    }


    public boolean checkPermissionForBack(HttpServletRequest request, HttpServletResponse response, String token) throws Exception {
        int platform = Integer.parseInt(request.getHeader("platform"));
        String urlPath = request.getRequestURI();

        Long id = Long.parseLong(JwtTokenUtil.getIdFromToken(token));
        TbUser user = userService.getByIdWithPermission(id);
        if (user == null) {
           throw new BusinessException(BusinessStatus.ILLEGAL_TOKEN);
        }

        if (user.getIsAdmin() == 1) {
            return true;
        }

        for (TbPermission permission : user.getPermissionList()) {
            if (permission.getBackendUrl() != null && permission.getBackendUrl().equals(urlPath)) {
                return true;
            }
        }

        throw new BusinessException(BusinessStatus.FORBIDDEN);
    }


    public boolean checkPermissionForFront(HttpServletRequest request, HttpServletResponse response) {

        //前端用户只能访问带有这两个入口的API
        String[] passUrl = {
                "/terminal/",
                "/km-terminal-api/"
        };
        String urlPath = request.getRequestURI();

        for (String pUrl : passUrl) {
            if (urlPath.contains(pUrl)) {
                return true;
            }
        }

        throw new BusinessException(BusinessStatus.FORBIDDEN);
    }


    //根据Field获得对应的Class
    private Class getClassByName(Class classObject, String name){
        Map<Class, List<Field>> fieldMap = new HashMap<>();
        Class returnClass = null;
        Class tempClass = classObject;
        while (tempClass != null) {
            fieldMap.put(tempClass, Arrays.asList(tempClass .getDeclaredFields()));
            tempClass = tempClass.getSuperclass();
        }

        for(Map.Entry<Class,List<Field>> entry: fieldMap.entrySet()){
            for (Field f : entry.getValue()) {
                if(f.getName().equals(name)){
                    returnClass = entry.getKey();
                    break;
                }
            }
        }
        return returnClass;
    }

    //递归遍历父类寻找coyoteRequest Field
    private Object findCoyoteRequest(Object request)  throws Exception {
        Class a = getClassByName(request.getClass(),"request");
        Field request1 = a.getDeclaredField("request");
        request1.setAccessible(true);
        Object b = request1.get(request);
        if(getClassByName(b.getClass(),"coyoteRequest") == null){
            return findCoyoteRequest(b);
        }else{
            return b;
        }
    }

}
